package com.loyal.camerax.ui.base

import android.app.Activity
import android.content.Intent
import android.content.res.Configuration
import android.os.Bundle
import android.util.Log
import android.view.KeyEvent
import android.widget.ImageButton
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import androidx.preference.PreferenceManager
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import com.loyal.camerax.R
import com.loyal.camerax.databinding.ActivityCameraBinding
import com.loyal.camerax.databinding.CameraUiContainerBinding
import com.loyal.camerax.databinding.CameraUiSettingsBinding
import com.loyal.camerax.impl.CameraConfigCallback
import com.loyal.camerax.impl.PicturePreviewCallback
import com.loyal.camerax.ui.settings.CameraSettingsActivity
import com.loyal.camerax.utils.ActivityHelper.hideSystemUI
import com.loyal.camerax.utils.ActivityHelper.screenOrientation
import com.loyal.camerax.utils.ActivityHelper.showRefuseDialog
import com.loyal.camerax.utils.MediaStoreUtils
import com.loyal.camerax.utils.PermissionHelper
import com.loyal.camerax.utils.PreferenceHelper
import com.loyal.camerax.utils.PreferenceHelper.get
import com.loyal.camerax.utils.delayClick
import com.loyal.camerax.utils.simulateClick
import com.loyal.camerax.view.TorchFlashMenu
import kotlinx.coroutines.launch

abstract class BaseCameraActivity : AppCompatActivity(),
    PicturePreviewCallback, CameraConfigCallback {
    protected val binding by lazy { ActivityCameraBinding.inflate(layoutInflater) }
    private val settingsBinding by lazy { binding.settingsPanel }
    private val cameraBinding by lazy { binding.cameraPanel }

    private val mediaStoreUtils by lazy { MediaStoreUtils(this) }

    private var permissionLauncher: ActivityResultLauncher<Array<String>>? = null
    private var settingsLauncher: ActivityResultLauncher<Intent>? = null

    fun settingsBinding(): CameraUiSettingsBinding {
        return settingsBinding
    }

    fun cameraBinding(): CameraUiContainerBinding {
        return cameraBinding
    }

    protected open fun orientationMutable(): Boolean {
        return intent.getBooleanExtra(PreferenceHelper.MUTABLE_ORIENTATION, false)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val orientationMutable = orientationMutable()
        Log.e(TAG, "屏幕方向是否可变: $orientationMutable")
        if (orientationMutable) screenOrientation()
        setContentView(binding.root)
        initPermission()
        initCamerax()
        updateCameraSettings()
    }

    private fun initPermission() {
        permissionLauncher =
            registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) {
                val cameraGranted = it[android.Manifest.permission.CAMERA] ?: false
                if (!cameraGranted) {
                    showRefuseDialog(settingsLauncher)
                }
            }
        settingsLauncher =
            registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
                val action = it.data?.action
                Log.e(TAG, "onCreateView: $action")
                if (PreferenceHelper.KEY_RESTART_ACTION == action) {
                    restart(this)
                } else if (PreferenceHelper.KEY_CHANGED_ACTION == action) {
                    updateCameraSettings()
                }
            }
        permissionLauncher?.launch(PermissionHelper.all())
    }

    override fun onResume() {
        super.onResume()
        binding.root.postDelayed({
            hideSystemUI()
        }, IMMERSIVE_FLAG_TIMEOUT)
    }

    override fun onConfigurationChanged(newConfig: Configuration) {
        super.onConfigurationChanged(newConfig)
        Log.e(TAG, "onConfigurationChanged: ")
    }

    protected fun setCameraUI() {
        lifecycleScope.launch {
            val thumbnailUri = mediaStoreUtils.getLatestImageFilename()
            thumbnailUri?.let {
                setGalleryThumbnail(it)
            }
        }
        settingsBinding().apply {
            flashSwitch.setOnClickListener {
                it.delayClick()
                switchFlash(flashSwitch)
            }
            cameraSetting.setOnClickListener {
                it.delayClick()
                CameraSettingsActivity.launch(
                    this@BaseCameraActivity,
                    settingsLauncher, R.id.settings_fragment, orientationMutable()
                )
            }
        }

        cameraBinding().apply {
            cameraCapture.setOnClickListener {
                takePhoto()
            }
            cameraGallery.setOnClickListener {
                openGallery()
            }
            cameraGallery.setOnLongClickListener {
                it.tag = null
                cameraGallery.setImageResource(R.drawable.ic_photo)
                true
            }
            cameraSwitch.setOnClickListener {
                it.delayClick()
                switchCamera()
            }
        }
    }

    override fun savePath(): String {
        return ""
    }

    override fun saveName(): String {
        return ""
    }

    override fun openGallery() {
        val tag = cameraBinding().cameraGallery.tag as? String?
        tag?.let {

        }
        CameraSettingsActivity.launch(
            this@BaseCameraActivity,
            settingsLauncher, R.id.gallery_fragment
        )
    }

    protected fun setGalleryThumbnail(filename: String) {
        val galleryView = cameraBinding().cameraGallery
        galleryView.post {
            Glide.with(galleryView).load(filename).apply(RequestOptions.circleCropTransform())
                .into(galleryView)
            galleryView.tag = filename
        }
    }

    protected open fun switchFlash(flashView: ImageButton) {
        if (null == popupMenu)
            intiFlashMenu(flashView)
        popupMenu?.show()
    }

    private var popupMenu: TorchFlashMenu? = null

    private fun intiFlashMenu(flashView: ImageButton) {
        popupMenu = TorchFlashMenu(this, flashView)
        popupMenu?.setOnTorchFlashChangedListener(object :
            TorchFlashMenu.OnTorchFlashChangedListener {
            override fun onTouchFlashChanged(state: String): Boolean {
                return updateTorchFlash(flashView, state)
            }
        })
    }

    open fun restart(activity: Activity) {
        Log.e(TAG, "restart: ")
        val paramsIntent = activity.intent
        val restartIntent = Intent(
            activity, activity.javaClass
        )
        paramsIntent?.let {
            restartIntent.putExtras(it)
        }
        activity.startActivity(restartIntent)
        activity.finish()
    }

    private fun updateCameraSettings() {
        val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
        val torchFlashValue = sharedPreferences.get(getString(R.string.flash_key))
        updateTorchFlash(settingsBinding.flashSwitch, torchFlashValue)
    }

    override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
        return when (keyCode) {
            KeyEvent.KEYCODE_VOLUME_UP, KeyEvent.KEYCODE_VOLUME_DOWN -> {
                binding.cameraPanel.cameraCapture.simulateClick()
                true
            }

            else -> super.onKeyDown(keyCode, event)
        }
    }

    companion object {
        private const val TAG = "BaseCameraActivity"
        private const val IMMERSIVE_FLAG_TIMEOUT = 500L

    }
}